/*
例程60. 记录个人资料
整理优化by:千百度QAIU
QQ:736226400
编译环境:gcc/tcc
2017/10/22
*/

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>

struct Family *get_person(void);    /* Prototype for input function */
char related(struct Family *pmember1, struct Family *pmember2);
char set_ancestry(struct Family *pmember1, struct Family *pmember2);

struct Date   
{
	int day;
	int month;
	int year;
};

struct Family                      /* Family structure declaration   */
{
	struct Date dob;
	char name[20];
	char father[20];
	char mother[20];
	struct Family *next;            /* Pointer to next structure      */
	struct Family *previous;        /* Pointer to previous structure  */
	struct Family *p_to_pa;         /* Pointer to father structure   */
	struct Family *p_to_ma;         /* Pointer to mother structure   */
};

int main()
{
	struct Family *first = NULL;    /* Pointer to first person        */
	struct Family *current = NULL;  /* Pointer to current person      */
	struct Family *last = NULL;     /* Pointer to previous person     */
	
	char more = '\0';               /* Test value for ending input    */
	
	for( ; ; )
	{
		printf("\nDo you want to enter details of a%s person (Y or N)? ", 
			first != NULL?"nother " : "" );
		scanf(" %c", &more);
		if(tolower(more) == 'n') 
			break;
		
		current = get_person();
		
		if(first == NULL)
		{
			first = current;            /* Set pointer to first Family    */
			last = current;             /* Remember for next iteration    */
		}
		else
		{
			last->next = current;  /* Set next address for previous Family */  
			current->previous = last; /* Set previous address for current */
			last = current;           /* Remember for next iteration */             
		}
	}	
	current = first;
	
	while(current->next != NULL)  /* Check for relation for each person in    */
	{                       /* the list up to second to last            */
		int parents = 0;      /* Declare parent count local to this block */
		last = current->next; /* Get the pointer to the next              */
		
		while(last != NULL)   /* This loop tests current person           */
		{                     /* against all the remainder in the list    */
			if(related(current, last))         /* Found a parent ?          */
				if(++parents == 2)   /* Yes, update count and check it        */
					break;             /* Exit inner loop if both parents found */
				
				last = last->next;     /* Get the address of the next           */
		} 
		current = current->next;   /* Next in the list to check             */
 }
	
	/* Now tell them what we know */
	
	/* Output Family data in correct order */
	current = first;
	
	while (current != NULL)  /* Output Family data in correct order  */
	{
		printf("\n%s was born %d/%d/%d, and has %s and %s as parents.",
			current->name, current->dob.day, current->dob.month,
			current->dob. year, current->father,  current->mother);
		if(current->p_to_pa != NULL )
			printf("\n\t%s's birth date is %d/%d/%d  ",
			current->father, current->p_to_pa->dob.day,
			current->p_to_pa->dob.month, 
			current->p_to_pa->dob.year);
		if(current->p_to_ma != NULL)
			printf("and %s's birth date is %d/%d/%d.\n  ",
			current->mother, current->p_to_ma->dob.day,
			current->p_to_ma->dob.month, 
			current->p_to_ma->dob.year);
		
		current = current->next;  /* current points to next in list       */
	}
	
	/* Now free the memory */  
	current = first;
	while(current->next != NULL)
	{
		last = current;     /* Save pointer to enable memory to be freed */
		current = current->next; /* current points to next in list       */
		free(last);         /* Free memory for last                      */
	}
	return 0;
}

/*   Function to input data on Family members   */
struct Family *get_person(void)
{
	struct Family *temp;         /* Define temporary structure pointer */
	
	/* Allocate memory for a structure */
	temp = (struct Family*) malloc(sizeof(struct Family));
	printf("\nEnter the name of the person: ");
	scanf("%s", temp -> name );         /* Read the Family's name */
	printf("\nEnter %s's date of birth (day month year); ", temp->name);
	scanf("%d %d %d", &temp->dob.day, &temp->dob.month, &temp->dob.year);
	printf("\nWho is %s's father? ", temp->name );
	scanf("%s", temp->father );        /* Get the father's name */
	printf("\nWho is %s's mother? ", temp -> name );
	scanf("%s", temp -> mother );      /* Get the mother's name */
	temp->next = temp->previous = NULL; /* Set pointers to NULL */
	temp->p_to_pa = temp->p_to_ma = NULL;    /* Set pointers to NULL  */
	return temp;          /* Return address of Family structure */
}

char set_ancestry(struct Family *pmember1, struct Family *pmember2)
{
	if(strcmp(pmember1->father, pmember2->name) == 0)
	{
		pmember1->p_to_pa = pmember2;
		return 1;
	}
	if( strcmp(pmember1->mother, pmember2->name) == 0)
	{
		pmember1->p_to_ma = pmember2;
		return 1;
	}
	else
		return 0;
}
/* Fill in pointers for mother or father relationships */
char related (struct Family *pmember1, struct Family *pmember2)
{
	return set_ancestry(pmember1, pmember2) ||
		set_ancestry(pmember2, pmember1);
}